﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using StructureTree;
using HexControl;
using FileModelNS;
using System.Diagnostics;

//TODO: 안전성 고려
//TODO: ASCII 값에 선택 기능 추가
//TODO: Format Structure(XML) 파일을 C++ 문법에서 자동으로 변환해주는 도구

//TODO: 모든 옵션 설정을 Configuration file(config.xml)로 빼내기
//TODO: 참조값에 대해서는 선택시에 참조에 사용된 값들도 보여주면 어떨까?
//TODO: 나중에 버그를 쉽게 찾을 수 있도록 사용자가 한 모든 행위들을 기록하는 장치 추가
//TODO: 긴 파일 이름을 생략해서 보여주기
//TODO: HexControl에서 ToolTip 보여줄 때 시간 계산해서 보여주기

//TODO: 애드인
//TODO: Redo/Undo
//TODO: Hex-Control 크기에 따른 자동 확장
//TODO: 횡 스크롤 지원(Hex Control)
//TODO: Export 기능(Structure에 맞게 데이터 저장, 16진수 또는 10진수)
//TODO: XML 확장 기능 정리
//TODO: 인쇄 기능
//TODO: Copy 기능
//TODO: Event-Driven 구조 정리
//TODO: 옵션 기능 고려


//TODO: (완료) 선택 블록 좀더 매끄럽게 보여주기 (widen)으로 해결 (Draw outline)
//TODO: (완료) 상대 주소 값 계산할 때 사칙 연산이 가능하도록 기능 확장 (Calculate relative variables)
//TODO: (완료) PE 헤더에 대한 파일 구조 완성(XML 문서 기능 확장)
//TODO: (완료) XML 문서에서 주석은 무시
//TODO: (완료) HEX에서 값을 선택하면 그게 역으로 XML node에 적용될 수 있도록(역선택 기능) 한다.
//TODO: (완료) HEX 값 편집 기능


namespace FormatVisualizer
{
    public partial class MainForm : Form
    {
    	private FileModel _FileModel;	

        public MainForm()
        {
            InitializeComponent();

        	_FileModel = new FileModel();
			hexControl.SetFileModel(_FileModel);
        	structureTree.SetFileModel(_FileModel);

			_FileModel.FileLoaded += new EventHandler(FileModel_FileLoaded);
			_FileModel.FormatLoaded += new EventHandler(FileModel_FormatLoaded);
			_FileModel.FormatUnloaded += new EventHandler(FileModel_FormatUnloaded);
			_FileModel.SelectedFormatNodeChanged += new EventHandler(FileModel_SelectedFormatNodeChanged);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
				OpenFileDialog openFileDialog = new OpenFileDialog();
				openFileDialog.Filter = "All files (*.*)|*.*|Executable files (*.exe)|*.exe|Image files (*.bmp, *.jpg, *.gif)|*.bmp;*.jpg;*.gif";
				openFileDialog.FilterIndex = 1;
				openFileDialog.RestoreDirectory = false;
				openFileDialog.AutoUpgradeEnabled = true;

	            if (openFileDialog.ShowDialog() == DialogResult.OK)
                	_FileModel.LoadFile(openFileDialog.FileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
            }
        }

        private void loadXmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ( _FileModel.IsFileLoaded == false) {
                MessageBox.Show("Error: Could not load XML file because a Binary file was not loaded");
                return;
            }

            try
            {
				OpenFileDialog openFileDialog = new OpenFileDialog();
				openFileDialog.Filter = "XML file(*.xml)|*.xml|All files (*.*)|*.*";
				openFileDialog.FilterIndex = 1;
				openFileDialog.RestoreDirectory = false;
				openFileDialog.AutoUpgradeEnabled = true;

				if (openFileDialog.ShowDialog() == DialogResult.OK)
               		_FileModel.LoadFormatFile(openFileDialog.FileName);
               }
            catch (Exception ex)
            {
                MessageBox.Show("Could not read file from disk. Original error: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

		private void FileModel_FileLoaded(object sender, EventArgs e)
		{
			Debug.Assert(_FileModel == sender);
			labelBinaryFile.Text = _FileModel.FileName;
		}
		
		private void FileModel_FormatLoaded(object sender, EventArgs e)
		{
			Debug.Assert(_FileModel == sender);
			labelXmlFile.Text = _FileModel.FormatFileName;
		}

		private void FileModel_FormatUnloaded(object sender, EventArgs e)
		{
			Debug.Assert(_FileModel == sender);
			labelXmlFile.Text = "";
		}

		private void FileModel_SelectedFormatNodeChanged(object sender, EventArgs e)
		{
			Debug.Assert(_FileModel == sender);

			var sfn = _FileModel.SelectedFormatNode;

			var fnp = new FormatNodeProperty();
			fnp.Text = sfn.Text;
			fnp.Path = sfn.Path;
			fnp.Comment = sfn.Comment;
			fnp.Offset = sfn.Offset;
			fnp.Size = sfn.Size;

			propertyNodeGrid.SelectedObject = fnp;
		}
    }
}
